package com.yhty.service.impl;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;

import org.h2.util.StringUtils;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.yhty.dao.OweDao;
import com.yhty.model.Owe;
import com.yhty.model.OweList;
import com.yhty.model.PayMent;
import com.yhty.model.WeMonth;
import com.yhty.service.OweManager;
import com.yhty.service.WeManager;
import com.yhty.utils.Arith;
import com.yhty.utils.DateUtil;

/**
 * 欠费处理业务逻辑实现类
 * 
 * @author RoySong 2011-3-31-上午11:24:25
 */
@Service("oweManager")
@Transactional
public class OweManagerImpl implements OweManager {
	private OweDao oweDao;
	private WeManager weManager;

	/*
	 * 全表扫描批量处理欠费信息
	 * 
	 * @see com.yhty.service.OweManager#dealOwe()
	 */
	public void dealOwe() {
		// 判断本月欠费信息是否生成，已生成则不执行方法，未生成则开始生成
		if (oweDao.isOweInit())
			return ;
		// 取出本月应缴的房租物管费用
		List<Owe> thisMonth = oweDao.getThisMonth();
		// 取出上月欠费信息
		List<Owe> lastMonth = oweDao.getByMonth(DateUtil.getLastMonthToday());
		// 取出本月应缴的水电费用
		weManager.init();
		List<WeMonth> wmList = weManager.getMonth();
		// 处理欠费和预交
		dealOweAndPrepare(thisMonth, lastMonth);
		// 处理本月应缴的水电费用
		dealWe(thisMonth, wmList);
		// 进行本月汇总处理
		dealAll(thisMonth);
		oweDao.batchAdd(thisMonth);
		// 更改初始化标识
		oweDao.init();
	}

	/**
	 * 进行本月汇总处理
	 * 
	 * @param thisMonth
	 */
	private void dealAll(List<Owe> thisMonth) {
		for (Owe owe : thisMonth) {
			dealOweAll(owe);
		}
	}

	/**
	 * 单条欠费信息汇总处理
	 * @param owe
	 */
	private void dealOweAll(Owe owe) {
		List<Float> sum = new ArrayList<Float>();
		sum.add(owe.getOwe_last());
		sum.add(owe.getOwe().getRent());
		sum.add(owe.getOwe().getManager());
		sum.add(owe.getOwe().getWater());
		sum.add(owe.getOwe().getElectric());
		owe.setAll(Arith.add(sum,sum.size()));
	}

	/**
	 * 处理本月应缴的水电费用
	 * 
	 * @param thisMonth
	 * @param wmList
	 */
	private void dealWe(List<Owe> thisMonth, List<WeMonth> wmList) {
		if (wmList.isEmpty())
			return ;
		for (Owe owe : thisMonth)
			for (WeMonth wm : wmList) {
				if (owe.getRent_id().longValue() != wm.getRent_id().longValue())
					continue;
				dealOweWe(owe, wm);
			}
	}

	/**
	 * 单条欠费记录水电处理
	 * @param owe
	 * @param wm
	 */
	private void dealOweWe(Owe owe, WeMonth wm) {
		owe.getOwe().setWater(Arith.add(owe.getOwe().getWater(),
				Arith.mul(wm.getW_price(), wm.getW_num())));
		owe.getOwe().setElectric(Arith.add(owe.getOwe().getElectric(),
				Arith.mul(wm.getE_price(), wm.getE_num())));
	}

	/**
	 * 根据上月的欠费信息列表处理本月欠费信息的欠费金额和预交情况
	 * 
	 * @param thisMonth
	 * @param lastMonth
	 */
	private void dealOweAndPrepare(List<Owe> thisMonth, List<Owe> lastMonth) {
		if (lastMonth.isEmpty())
			return;
		for (Owe now : thisMonth)
			for (Owe last : lastMonth) {
				if (now.getRent_id().longValue() != last.getRent_id()
						.longValue()|| last.getAll() == 0)
					continue;
				dealOweLast(now, last);
			}
	}

	/**
	 * 单条欠费记录上月预交和欠费处理
	 * @param now
	 * @param last
	 */
	private void dealOweLast(Owe now, Owe last) {
		if (last.getAll() < 0) {// 上月有预交余额
			List<Float> sum = new ArrayList<Float>();
			sum.add(last.getAll());
			sum.add(now.getOwe().getRent());
			sum.add(now.getOwe().getManager());
			float restPrepare = Arith.add(sum, sum.size());
			if (restPrepare <= 0) {// 上月预交余额足以缴纳本月房租物管
				now.getOwe().setRent(new Float(0));
				now.getOwe().setManager(new Float(0));
				now.setAll(restPrepare);
			}
		}
		// 上月预交余额不足以缴纳本月房租物管或者上月有欠款
		now.setOwe_last(last.getAll());
		now.getOwe().setWater(last.getOwe().getWater());
		now.getOwe().setElectric(last.getOwe().getElectric());
	}

	@Resource(name = "oweDao")
	public void setOweDao(OweDao oweDao) {
		this.oweDao = oweDao;
	}

	@Resource(name = "weManager")
	public void setWeManager(WeManager weManager) {
		this.weManager = weManager;
	}

	/*
	 * 根据本月缴费情况更新欠费记录
	 * 
	 * @see com.yhty.service.OweManager#updateOwe(com.yhty.model.PayMent)
	 */
	public void updateOwe(PayMent payMent) {
		Owe owe = null;
		try {
			owe = oweDao.getByRentId(DateUtil.getToday(), payMent.getRent_id());
		} catch (EmptyResultDataAccessException e) {
			throw new RuntimeException("rent_id=" + payMent.getRent_id()
					+ " 本月初始化记录不存在");
		}
		if (payMent.getPay() != null) {
			//更新房租物管欠费记录
			if (payMent.getPay().getRent() != null
					&& payMent.getPay().getRent().floatValue()>0) {
				owe.getOwe().setRent(Arith.sub(owe.getOwe().getRent(),
						payMent.getPay().getRent()));
				owe.getOwe().setManager(Arith.sub(owe.getOwe().getManager(),
						payMent.getPay().getManager()));
			}
			//更新水费欠款记录
			if(payMent.getPay().getWater() != null
					&& payMent.getPay().getWater().floatValue()>0){
				owe.getOwe().setWater(Arith.sub(owe.getOwe().getWater(),
						 payMent.getPay().getWater()));
			}
			//更新电费欠款记录
			if(payMent.getPay().getElectric()!=null
					&& payMent.getPay().getElectric().floatValue()>0){
				owe.getOwe().setElectric(Arith.sub(owe.getOwe().getElectric(),
						payMent.getPay().getElectric()));
			}
		}
		//更新累计欠费记录
		if(payMent.getOwe()!=null){
			List<Float> sub = new ArrayList<Float>();
			sub.add(owe.getOwe_last());
			sub.add(payMent.getOwe().getRent());
			sub.add(payMent.getOwe().getManager());
			sub.add(payMent.getOwe().getWater());
			sub.add(payMent.getOwe().getElectric());
			owe.setOwe_last(Arith.sub(sub, sub.size()));
		}
		//根据预交更新总欠费记录
		if(payMent.getPrepare()!=null){
			List<Float> sub = new ArrayList<Float>();
			sub.add(owe.getAll());
			sub.add(payMent.getPrepare().getRent());
			sub.add(payMent.getPrepare().getManager());
			owe.setAll(Arith.sub(sub, sub.size()));
		}
		//更新滞纳金欠费记录
		if(payMent.getDelay()!=null&&payMent.getDelay().floatValue()!=0)
			owe.setDelay(Arith.sub(owe.getDelay(),payMent.getDelay()));
		//汇总欠费记录
		List<Float> sum = new ArrayList<Float>();
		sum.add(owe.getAll());
		sum.add(owe.getOwe_last());
		sum.add(owe.getOwe().getRent());
		sum.add(owe.getOwe().getManager());
		sum.add(owe.getOwe().getWater());
		sum.add(owe.getOwe().getElectric());
		owe.setAll(Arith.add(sum, sum.size()));
		oweDao.update(owe);
	}

	/*
	 * 根据月份获取欠费记录
	 * @see com.yhty.service.OweManager#getByMonth(java.lang.String)
	 */
	public List<OweList> getByMonth(String date) {
		if(StringUtils.isNullOrEmpty(date))
			date = DateUtil.getToday();
		return oweDao.getOweListByMonth(date);
	}

	/*
	 * 欠费重置
	 * @see com.yhty.service.OweManager#reset(com.yhty.model.Owe)
	 */
	public void reset(Owe owe) {
		// 处理欠费和预交
		Owe now = oweDao.getThisMonthOwe(owe.getRent_id());
		if(now == null)
			throw new RuntimeException("rent_id=" + owe.getRent_id()
					+ " 租房记录不存在");
		now.setId(owe.getId());
		Owe last = oweDao.getByRentId(
				DateUtil.getLastMonthToday(), owe.getRent_id());
		if(last != null)
			dealOweLast(now, last);
		//取出本月应缴的水电费用
		WeMonth wm = weManager.getByRentId(owe.getRent_id(),
				DateUtil.getToday());
		// 处理本月应缴的水电费用
		if(wm != null)
			dealOweWe(now, wm);
		// 进行本月汇总处理
		dealOweAll(now);
		oweDao.update(now);
	}

}
